home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
cpp_libs
/
rwvector.lha
/
RWVector2.1
/
rw
/
DCosineFFT.h
< prev
next >
Wrap
C/C++ Source or Header
|
1989-08-18
|
5KB
|
148 lines
#ifndef DCOSINEFFT_H
#define DCOSINEFFT_H
#pragma once
/*
* Double Precision Fast Cosine server
*
* Copyright (C) 1988, 1989.
*
* Dr. Thomas Keffer
* Rogue Wave Associates
* P.O. Box 85341
* Seattle WA 98145-1341
*
* Permission to use, copy, modify, and distribute this
* software and its documentation for any purpose and
* without fee is hereby granted, provided that the
* above copyright notice appear in all copies and that
* both that copyright notice and this permission notice
* appear in supporting documentation.
*
* This software is provided "as is" without any
* expressed or implied warranty.
*
*
* @(#)DCosineFFT.h 2.1 8/18/89
*/
#include "DoubleFFT.h"
/* The transform of a real, even sequence is a cosine transform.
The transform of a real, odd sequence is a sine transform.
************* E V E N S E Q U E N C E ****************
A real "even" vector is one that is symmetric, i.e., V(j) == V(-j), or
V(j) == V(2N-j) where 2N is the total length of the vector. Of the 2N
points, only the N+1 points V(j), j =0,...,N need be given. Hence, N
== V.length()-1. The upper half of V can be recovered from V(j) =
V(2N-j),j=N+1,...,2N-1. This means that of the total 2N sequence, N-1
values are repeated twice, and two [V(0) and V(N)] are unique, for a
total of 2N points, of which only N+1 are actually stored.
V(0), V(1), ... V(N), V(N+1), V(N+1), ... V(2N-1)
^ ^
| | V(N-1), V(N-2), ... V(1) <---reflection
+---------------+
N+1 points
stored
The inverse fourier transform (IDFT) of a real even sequence is a
cosine transform. The result is also a real even sequence. The
transform is defined as follows. Assume (as above) that V(j),
j=0,1,2,...,2N-1 is real and that V(j) == V(2N-j). Then
2N-1
V(j) = sum C(n) exp(pi * n * j * I / N)
n=0
or
N-1
V(j) = a(0)/2 + sum a(n) cos(pi * j * n / N) + 0.5*(-1)**j * a(N)
n=1
where the a(n)'s are real and a(n) = 2C(n).
It also follows that the forward fourier transform (DFT) of V(j) can
be expressed as a cosine series:
N-1
a(n) = (2/N)*(V(0)/2 + sum V(j) cos(pi * j * n / N) + 0.5*(-1)**n * V(N))
j=1
The real part of C(n) is what is actually returned by cosine().
************* O D D S E Q U E N C E ****************
A real "odd" vector is one that is anti-symmetric, i.e., V(j) ==
-V(-j), or V(j) == -V(2N-j). As above, the vector V should be thought
of as 2N points long, but, here, only the points V(j), j=1,...,N-1, a
total of N-1 points (rather than N+1), need be given. This is because
we know that V(0) and V(N) must always be zero for the sequence to be
odd. Hence, N == length()+1. This means that of the total 2N
sequence, N-1 values are repeated twice, and two are always zero, for
a total of 2N points, of which only N-1 are actually stored.
V(0), V(1), ... V(N-1), V(N), V(N+1), V(N+1), ... V(2N-1)
^ ^ ^ ^
| | | | V(N-1), V(N-2), ... V(1) <---reflection
| +----------+ |
always -+ N-1 points +--always
zero stored zero
The sine transform is defined as:
N-1
V(j) = sum b(n) sin(pi * j * n / N)
n=1
and
N-1
b(n) = (2/N) * ( sum V(j) sin(pi * j * n / N).
j=1
The imaginary part of C(n) is what is actually returned by sine().
************* N O T E S ****************
Due to an algorithmic limitation, the cosine and sine transforms are
limited to sequences with N even. In other words, the length() of the
vector V must be odd. Too bad!
Speed Note: In general, one has the choice of using a cosine
transform, or expanding the series out to the full series and using a
regular complex FFT, saving only the lower half of the real part. The
cosine transform is at its worst relative to the full complex fft for
short series that are a power of 2 in length (empirically, series that
are 32, 16, 8, etc. points long). In this case, you might want to
consider using the complex transform. But for longer series, or
series that are not a power of 2 long, you are better off using the
cosine server. This also has the advantage of leaving yourself open
to later optimizations. */
class DoubleCosineServer : public DoubleFFTServer {
unsigned server_N;
DoubleVec sins;
protected:
void checkOdd(int);
public:
DoubleCosineServer();
DoubleCosineServer(unsigned N);
DoubleCosineServer(const DoubleCosineServer&);
void operator=(const DoubleCosineServer&);
unsigned order() {return server_N;}
void setOrder(unsigned); // Set new server_N
/*********** TRANSFORMS ***********/
// Returns DFT of a real even sequence, which is an even sequence:
DoubleVec cosine(const DoubleVec& v);
// Returns DFT of a real odd sequence, which is an odd sequence:
DoubleVec sine(const DoubleVec& v);
};
#endif